#include "dhashblockingclient.hh"

#include <cstring>

#include <chord.h>
#include <dhash_common.h>
#include <dhblock.h>

bigint DhashBlockingClient::insert(const char *buf, size_t buflen) throw(DhashInsertException){
	bigint key=compute_hash(buf,buflen);
	return insert(key, buf, buflen);
}

bigint DhashBlockingClient::insert(bigint key, const char *buf, size_t buflen, bool key_is_hash) throw(DhashInsertException){
	warn << "DhashBlockingClient::insert() - start\n";
	dhash_ctype c = key_is_hash?DHASH_CONTENTHASH:DHASH_NOAUTH;

	write_ok = false;
	m_client->insert(key,buf,buflen,wrap(this, &DhashBlockingClient::insert_cb),NULL,c);
	
	wait_for_cb();

	if (!write_ok)
		throw new DhashInsertException();
	warn << "DhashBlockingClient::insert() - stop\n";
	return key;
}

void DhashBlockingClient::insert_cb(dhash_stat stat, ptr<insert_info> info) {
	cb_ok=true;
	warn << "DhashBlockingClient::insert_cb() - start\n";
	warn << "dhash_stat = " << stat << "\n";
	if(stat != DHASH_OK)
		return;
	write_ok = true;
	warn << "DhashBlockingClient::insert_cb() - stop\n";
}

str DhashBlockingClient::retrieve(bigint key, bool key_is_hash) throw(DhashRetrieveException) {
	dhash_ctype c = key_is_hash?DHASH_CONTENTHASH:DHASH_NOAUTH;

	read_ok=false;
	str tmp;
	
	m_client->retrieve(key,c,wrap(this, &DhashBlockingClient::retrieve_cb, &tmp));

	wait_for_cb();

	if (!read_ok)
		throw new DhashRetrieveException();
	return tmp;
}

void DhashBlockingClient::retrieve_cb(str *buf, dhash_stat stat, ptr<dhash_block> bl, vec<chordID> vc) {
	cb_ok=true;
	warn << "DhashBlockingClient::retrieve_cb stat= " << stat << "\n";

//	warn << "DhashBlockingClient::retrieve_cb bl->data: >" << bl->data << "< " << bl->data.len() << "\n";
//	warn << "DhashBlockingClient::retrieve_cb bl->vData.size(): " << bl->vData.size() << "\n";

	if (bl->vData.size()==0) {
		*buf=bl->data;
	} else {
//		for (size_t i=0; i< bl->vData.size(); ++i) {
//			warn << "\tLOOP: vData[" << i << "]= >" << bl->vData[i] << "<\n";
//		}
		*buf = bl->vData[bl->vData.size()-1];
	}

	read_ok=true;
	return;
}

void DhashBlockingClient::wait_for_cb() {
	cb_ok=false;

	while (!cb_ok) {
		warn << "wait_for_cb - iter()\n";
		acheck();
	}
}
/*
class BlockWriter {
	public:
		virtual chordID writeBlock(void *data,unsigned int len) {
			chordID id=compute_hash(data,len);
			writeBlock(chordID,data,len);
			return chordID;
		}
		virtual void writeBlock(chordID key, void *data, unsigned int len)=0;
};

class BlockReader {
	public:
		void readBlock(chordID key,void **data, unsigned int &len)=0;
};
*/
